import { useEffect, useCallback, useRef, useState } from 'react';
import type { Position } from '../types';

/**
 * Modal Sheet 核心逻辑 Hook 的参数接口
 */
interface UseModalSheetProps {
  open: boolean;
  onClose: () => void;
  closeOnEscape?: boolean;
  closeOnOverlayClick?: boolean;
  lockScroll?: boolean;
  autoFocus?: boolean;
  trapFocus?: boolean;
  onBeforeOpen?: () => void;
  onAfterOpen?: () => void;
  onBeforeClose?: () => void;
  onAfterClose?: () => void;
}

/**
 * Modal Sheet 核心逻辑 Hook
 */
export const useModalSheet = (props: UseModalSheetProps) => {
  const {
    open,
    onClose,
    closeOnEscape = true,
    closeOnOverlayClick = true,
    lockScroll = true,
    autoFocus = true,
    trapFocus = true,
    onBeforeOpen,
    onAfterOpen,
    onBeforeClose,
    onAfterClose,
  } = props;

  const modalRef = useRef<HTMLDivElement>(null);
  const overlayRef = useRef<HTMLDivElement>(null);
  const previousActiveElement = useRef<HTMLElement | null>(null);
  const [isAnimating, setIsAnimating] = useState(false);

  // 处理 ESC 键关闭
  
  const handleEscapeKey = useCallback(
    (event: KeyboardEvent) => {
      if (event.key === 'Escape' && closeOnEscape && open) {
        event.preventDefault();
        onClose();
      }
    },
    [closeOnEscape, open, onClose]
  );

  // 处理点击遮罩层关闭
  // 具体代码实现：当用户点击遮罩层时，如果遮罩层是动画状态，则不关闭弹框；如果遮罩层是静态状态，则关闭弹框。
  const handleOverlayClick = useCallback(
    (event: React.MouseEvent<HTMLDivElement>) => {
      if (
        closeOnOverlayClick &&
        event.target === overlayRef.current &&
        !isAnimating
      ) {
        onClose();
      }
    },
    [closeOnOverlayClick, onClose, isAnimating]
  );

  // 焦点陷阱 确保焦点在弹框内循环，提升可访问性
  // 具体实现：当用户按下 Tab 键时，如果焦点在第一个可聚焦元素上，则将焦点移到最后一个可聚焦元素上；如果焦点在最后一个可聚焦元素上，则将焦点移到第一个可聚焦元素上。
  const handleKeyDown = useCallback(
    (event: KeyboardEvent) => {
      if (!trapFocus || !open || !modalRef.current) return;

      const focusableElements = modalRef.current.querySelectorAll(
        'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
      );
      const firstElement = focusableElements[0] as HTMLElement;
      const lastElement = focusableElements[
        focusableElements.length - 1
      ] as HTMLElement;

      if (event.key === 'Tab') {
        if (event.shiftKey) {
          if (document.activeElement === firstElement) {
            event.preventDefault();
            lastElement?.focus();
          }
        } else {
          if (document.activeElement === lastElement) {
            event.preventDefault();
            firstElement?.focus();
          }
        }
      }
    },
    [trapFocus, open]
  );

  // 锁定页面滚动
  const lockBodyScroll = useCallback(() => {
    if (!lockScroll) return;

    const body = document.body;
    const scrollBarWidth =
      window.innerWidth - document.documentElement.clientWidth;

    body.style.overflow = 'hidden';
    body.style.paddingRight = `${scrollBarWidth}px`;
    body.classList.add('modal-sheet-scroll-lock');
  }, [lockScroll]);

  const unlockBodyScroll = useCallback(() => {
    if (!lockScroll) return;

    const body = document.body;
    body.style.overflow = '';
    body.style.paddingRight = '';
    body.classList.remove('modal-sheet-scroll-lock');
  }, [lockScroll]);

  // 自动聚焦
  const focusModal = useCallback(() => {
    if (!autoFocus || !modalRef.current) return;

    const focusableElement = modalRef.current.querySelector(
      'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
    ) as HTMLElement;

    if (focusableElement) {
      focusableElement.focus();
    } else {
      modalRef.current.focus();
    }
  }, [autoFocus]);

  // 恢复焦点
  const restoreFocus = useCallback(() => {
    if (previousActiveElement.current) {
      previousActiveElement.current.focus();
      previousActiveElement.current = null;
    }
  }, []);

  // 打开 Modal
  useEffect(() => {
    if (open) {
      // 保存当前焦点元素
      previousActiveElement.current = document.activeElement as HTMLElement;

      // 执行打开前回调
      onBeforeOpen?.();

      setIsAnimating(true);
      lockBodyScroll();

      // 延迟聚焦，等待动画开始
      const focusTimer = setTimeout(() => {
        focusModal();
        setIsAnimating(false);
        onAfterOpen?.();
      }, 50);

      return () => clearTimeout(focusTimer);
    } else {
      // 执行关闭前回调
      onBeforeClose?.();

      setIsAnimating(true);

      // 延迟解锁滚动和恢复焦点，等待动画完成
      const cleanupTimer = setTimeout(() => {
        unlockBodyScroll();
        restoreFocus();
        setIsAnimating(false);
        onAfterClose?.();
      }, 300); // 与 CSS 动画时间保持一致

      return () => clearTimeout(cleanupTimer);
    }
  }, [
    open,
    onBeforeOpen,
    onAfterOpen,
    onBeforeClose,
    onAfterClose,
    lockBodyScroll,
    unlockBodyScroll,
    focusModal,
    restoreFocus,
  ]);

  // 绑定键盘事件
  useEffect(() => {
    if (open) {
      document.addEventListener('keydown', handleEscapeKey);
      document.addEventListener('keydown', handleKeyDown);

      return () => {
        document.removeEventListener('keydown', handleEscapeKey);
        document.removeEventListener('keydown', handleKeyDown);
      };
    }
  }, [open, handleEscapeKey, handleKeyDown]);

  // 组件卸载时清理
  useEffect(() => {
    return () => {
      unlockBodyScroll();
      restoreFocus();
    };
  }, [unlockBodyScroll, restoreFocus]);

  return {
    modalRef,
    overlayRef,
    isAnimating,
    handleOverlayClick,
  };
};

/**
 * 拖拽功能 Hook
 */
export const useDraggable = (
  enabled: boolean,
  onDragStart?: (event: MouseEvent | TouchEvent) => void,
  onDrag?: (event: MouseEvent | TouchEvent, position: Position) => void,
  onDragEnd?: (event: MouseEvent | TouchEvent, position: Position) => void
) => {
  const [isDragging, setIsDragging] = useState(false);
  const [position, setPosition] = useState<Position>({ x: 0, y: 0 });
  const [startPosition, setStartPosition] = useState<Position>({ x: 0, y: 0 });
  const dragRef = useRef<HTMLDivElement>(null);

  // 预绑定事件监听器，避免第一次拖拽延迟
  const isInitialized = useRef(false);

  const handleMouseDown = useCallback(
    (event: React.MouseEvent<HTMLDivElement>) => {
      if (!enabled || !dragRef.current) return;

      event.preventDefault();
      setIsDragging(true);

      // 记录初始鼠标位置（绝对位置）
      const startPos = {
        x: event.clientX,
        y: event.clientY,
      };
      setStartPosition(startPos);

      // 重置位置偏移为0（从当前位置开始拖拽）
      setPosition({ x: 0, y: 0 });

      onDragStart?.(event.nativeEvent);
    },
    [enabled, onDragStart]
  );

  const handleMouseMove = useCallback(
    (event: MouseEvent) => {
      if (!isDragging || !dragRef.current) return;

      event.preventDefault();
      event.stopPropagation();

      // 立即执行，确保拖拽响应无延迟
      const newPosition = {
        x: event.clientX - startPosition.x,
        y: event.clientY - startPosition.y,
      };

      setPosition(newPosition);
      onDrag?.(event, newPosition);
    },
    [isDragging, startPosition, onDrag]
  );

  const handleMouseUp = useCallback(
    (event: MouseEvent) => {
      if (!isDragging) return;

      event.preventDefault();
      event.stopPropagation();

      setIsDragging(false);
      onDragEnd?.(event, position);
    },
    [isDragging, position, onDragEnd]
  );

  // 触摸事件处理
  const handleTouchMove = useCallback(
    (event: TouchEvent) => {
      if (!isDragging || !dragRef.current) return;

      event.preventDefault();
      event.stopPropagation();

      // 立即执行，确保触摸拖拽响应无延迟
      const touch = event.touches[0];
      // 计算相对于初始触摸位置的偏移量
      const newPosition = {
        x: touch.clientX - startPosition.x,
        y: touch.clientY - startPosition.y,
      };

      setPosition(newPosition);
      onDrag?.(event, newPosition);
    },
    [isDragging, startPosition, onDrag]
  );

  const handleTouchEnd = useCallback(
    (event: TouchEvent) => {
      if (!isDragging) return;

      event.preventDefault();
      event.stopPropagation();

      setIsDragging(false);
      onDragEnd?.(event, position);
    },
    [isDragging, position, onDragEnd]
  );

  // 优化：预绑定事件监听器，避免第一次拖拽延迟
  useEffect(() => {
    if (enabled && !isInitialized.current) {
      // 预绑定所有事件监听器，使用 passive: false 确保可以 preventDefault
      document.addEventListener('mousemove', handleMouseMove, {
        passive: false,
      });
      document.addEventListener('mouseup', handleMouseUp, {
        passive: false,
      });
      document.addEventListener('touchmove', handleTouchMove, {
        passive: false,
      });
      document.addEventListener('touchend', handleTouchEnd, {
        passive: false,
      });

      isInitialized.current = true;

      return () => {
        document.removeEventListener('mousemove', handleMouseMove);
        document.removeEventListener('mouseup', handleMouseUp);
        document.removeEventListener('touchmove', handleTouchMove);
        document.removeEventListener('touchend', handleTouchEnd);
        isInitialized.current = false;
      };
    }
  }, [
    enabled,
    handleMouseMove,
    handleMouseUp,
    handleTouchMove,
    handleTouchEnd,
  ]);

  // 重置拖拽状态，用于Modal关闭时快速清理
  const resetDragState = useCallback(() => {
    setIsDragging(false);
    setPosition({ x: 0, y: 0 });
    setStartPosition({ x: 0, y: 0 });
  }, []);

  return {
    dragRef,
    isDragging,
    position,
    handleMouseDown,
    resetDragState,
  };
};

/**
 * Portal 渲染 Hook
 */
export const usePortal = (container?: HTMLElement | (() => HTMLElement)) => {
  const [portalContainer, setPortalContainer] = useState<HTMLElement | null>(
    null
  );

  useEffect(() => {
    let targetContainer: HTMLElement;

    if (container) {
      targetContainer =
        typeof container === 'function' ? container() : container;
    } else {
      // 创建默认容器
      let defaultContainer = document.getElementById('modal-sheet-root');
      if (!defaultContainer) {
        defaultContainer = document.createElement('div');
        defaultContainer.id = 'modal-sheet-root';
        document.body.appendChild(defaultContainer);
      }
      targetContainer = defaultContainer;
    }

    setPortalContainer(targetContainer);
  }, [container]);

  return portalContainer;
};
